package lab.muilt;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ValueSelectorTree {
	private Context context;
	private Node root;

	public ValueSelectorTree(Context context) {
		this.context = context;
	}

	public void addMapValue(Map<String, Object> map) {
		if (root == null) {
			root = new Node("root");
		}
		Node parent = root;
		String[] keyNames = context.getKeyNames();
		Object[] keyValues = context.getKeys(map);
		if (keyNames.length != keyValues.length) {
			throw new IllegalStateException("keyNames length not equals with keyValues length: " + keyNames.length + " != " + keyValues.length);
		}
		Object[] values = context.getValues(map);
		for (int i = 0; i < keyValues.length; i++) {
			String keyName = keyNames[i];
			Object key = keyValues[i];
			Node child = new Node(key);
			if (context.isDefaultValue(keyName, key)) {
				parent.addDefaultChild(child);
			} else {
				parent.addChildNode(child);
			}
			parent = child;
		}
		parent.setValue(values);
	}

	public Map<String, Object> selectMapValue(Object[] keys) {
		String[] keyNames = context.getKeyNames();
		if (keys.length != keyNames.length) {
			throw new IllegalArgumentException("keys length not match key names length");
		}
		int length = keyNames.length;
		List<Node> nodeQueue = new ArrayList<Node>();
		nodeQueue.add(root);
		for (int i = 0; i < length && nodeQueue.size() > 0; i++) {
			Object key = keys[i];
			String keyName = keyNames[i];
			boolean isDefaultValue = context.isDefaultValue(keyName, key);
			List<Node> tempNodeQueue = new ArrayList<Node>();
			for (Node node : nodeQueue) {
				if (node.hasDefaultChild()) {
					tempNodeQueue.add(node.getDefaultChild());
				}
				if (!isDefaultValue) {
					Node child = node.getChildNode(key);
					if (child != null) {
						tempNodeQueue.add(child);
					}
				}
			}
			nodeQueue = tempNodeQueue;
		}
		if (nodeQueue.size() > 0) {
			Node node = nodeQueue.get(nodeQueue.size() - 1);
			Object value = node.getValue();
			if (value == null || !(value instanceof Object[])) {
				return null;
			}
			Object[] values = (Object[]) value;
			String[] valueNames = context.getValueNames();
			if (values.length != valueNames.length) {
				throw new IllegalArgumentException("illegal values: " + Arrays.toString(values) + ", can not match valueNames length: " + valueNames.length);
			}
			Map<String, Object> map = new HashMap<String, Object>();
			for (int i = 0; i < valueNames.length; i++) {
				map.put(valueNames[i], values[i]);
			}
			return map;
		} else {
			return null;
		}
	}
}
